﻿using System;
using Server.Engines.Craft;
using Server.Engines.Harvest;
using Server.Targeting;

namespace Server.Items
{
    public class FishingNet : FishingTool
    {
        private const int m_ticksCount = 6;
        private const double m_ticksTime = 5.0;
        private const int m_ticksFish = 5;

        private bool m_inUse = false;
        private DateTime m_playerLastMove;

        public override int MaxRange { get { return 4; } }

        public override double Chance { get { return 0.8; } }

        public override TimeSpan Delay { get { return TimeSpan.FromSeconds(30); } }

        public override FishEntry[] AvailableFishes
        {
            get
            {
                return new FishEntry[]
                {
                    new FishEntry(70.0, 0.0, 100.0, 0.250, typeof(Anchovy)),
                    new FishEntry(70.0, 0.0, 100.0, 0.500, typeof(Herring)),
                    new FishEntry(70.0, 0.0, 100.0, 0.750, typeof(Sardine)),
                    new FishEntry(70.0, 0.0, 100.0, 0.900, typeof(Capelin)),
                    new FishEntry(70.0, 0.0, 100.0, 0.980, typeof(ScorpionFish)),
                    new FishEntry(70.0, 0.0, 100.0, 0.990, typeof(RedScorpionFish)),
                    //Algue bleu
                    //Algue rouge
                    new FishEntry(70.0, 0.0, 100.0, 1.000, typeof(TreasureMap)),
                };
            }
        }

        public override bool UseDeepWater { get { return true; } }

        public override int FishingReqSkill { get { return 70; } }

        [Constructable]
        public FishingNet()
            : base(0x0DCA)
        {
            Stackable = false;
            Weight = 1.0;
            m_usesRemaining = 200;
            InvalidateProperties();
        }

        public FishingNet(Serial serial)
            : base(serial)
        { }

        public override void GetProperties(ObjectPropertyList list)
        {
            list.Add("Filet de pêche");
            list.Add("Durabilité : {0}", UsesRemaining);
            list.Add("Pêche requis : {0}", FishingReqSkill);
        }

        private bool CheckFishing(Mobile from)
        {
            if (from.Mounted)
            {
                from.SendMessage("Vous ne pouvez pas lancer un filet depuis une monture !");
                return false;
            }
            if (UsesRemaining <= 0)
            {
                from.SendMessage("Votre outils est cassé !");
                return false;
            }
            if (Deleted)
            {
                from.SendMessage("L'objet a été supprimer !");
                return false;
            }
            if (m_inUse)
            {
                from.SendMessage("Quelqu'un est déjà en train de pêcher avec ce filet !");
                return false;
            }
            if (!IsChildOf(from.Backpack))
            {
                from.SendMessage("Le filet doit être dans votre inventaire pour l'utiliser !");
                return false;
            }
            if (!from.HasFreeHand())
            {
                from.SendMessage("Vous devez avoir les mains libre pour lancer un filet !");
                return false;
            }

            return true;
        }

        public override void OnDoubleClick(Mobile from)
        {
            if (!CheckFishing(from))
                return;

            from.SendMessage("Où souhaitez vous lancer le filet ?");
            from.BeginTarget(-1, true, TargetFlags.None, new TargetCallback(OnTarget));
        }

        public void OnTarget(Mobile from, object target)
        {
            if (!CheckFishing(from))
                return;

            int tileID;
            Map map;
            Point3D loc;

            if (!HarvestHelper.GetTargetDetails(from, this, target, out tileID, out map, out loc))
                return;

            if (!Fishing.ValidateTarget(tileID, true))
                return;

            if (!Fishing.CheckDeepWater(from, this, map, loc))
                return;

            if (!Fishing.CheckRange(from, loc, map, this))
                return;

            m_inUse = true;
            Movable = false;
            MoveToWorld(loc, map);

            DoEffects(from, loc);

            Timer.DelayCall(TimeSpan.FromSeconds(1.5), TimeSpan.FromSeconds(m_ticksTime), m_ticksCount, new TimerStateCallback(DoFishing), new object[] { loc, 0, from, map });

            m_playerLastMove = from.LastMoveTime;
            from.SendMessage("Vous plongez le filet dans l'eau...");
        }

        private static void DoEffects(Mobile from, Point3D loc)
        {
            from.RevealingAction();
            from.Direction = from.GetDirectionTo(loc);
            from.Animate(12, 5, 1, true, false, 0);
        }

        private void DoFishing(object state)
        {
            object[] states = (object[])state;
            Point3D loc = (Point3D)states[0];
            int index = (int)states[1];
            Mobile from = (Mobile)states[2];
            Map map = (Map)states[3];

            states[1] = ++index;

            if (Deleted || !m_inUse)
                return;

            DoEffect(from, loc, index);

            if (m_playerLastMove < from.LastMoveTime || index == m_ticksCount)
            {
                from.SendMessage("Vous remontez votre filet...");
                EndFishing(from, map, loc, index);
            }
        }

        private void EndFishing(Mobile from, Map map, Point3D loc, int round)
        {
            int totalFish = 0;

            for (int i = 0; i < round; i++)
            {
                Type type = Fishing.GetResource(from, this, map, loc);

                if (type == null)
                    continue;

                int count = Utility.Random(m_ticksFish);

                for (int j = 0; j < count; j++)
                {
                    Item item = HarvestHelper.Construct(type, from);

                    if (item == null)
                        continue;

                    if (!HarvestHelper.Give(from, item, true))
                    {
                        from.SendMessage("Vous n'avez pas assez de place dans votre sac !");
                        item.Delete();
                        return;
                    }

                    totalFish++;
                }
            }

            if (totalFish > 0)
                from.SendMessage("Vous avez pêché {0} poissons !", totalFish);

            HarvestHelper.Give(from, this, true);
            m_inUse = false;
            Movable = true;
        }

        private void DoEffect(Mobile from, Point3D loc, int index)
        {
            if (index == 1)
            {
                Effects.SendLocationEffect(loc, Map, 0x352D, 16, 4);
                Effects.PlaySound(loc, Map, 0x364);
            }
            else if (index <= m_ticksFish)
            {
                for (int i = 0; i < 3; ++i)
                {
                    int x, y;

                    switch (Utility.Random(8))
                    {
                        default:
                        case 0: x = -1; y = -1; break;
                        case 1: x = -1; y = 0; break;
                        case 2: x = -1; y = +1; break;
                        case 3: x = 0; y = -1; break;
                        case 4: x = 0; y = +1; break;
                        case 5: x = +1; y = -1; break;
                        case 6: x = +1; y = 0; break;
                        case 7: x = +1; y = +1; break;
                    }

                    Effects.SendLocationEffect(new Point3D(loc.X + x, loc.Y + y, loc.Z), Map, 0x352D, 16, 4);
                }

                Effects.PlaySound(loc, Map, 0x364);
                this.Z -= 1;
            }
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);

            writer.Write((int)0); // version
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version = reader.ReadInt();
        }
    }
}
